/**
  ******************************************************************************
  * @file    can.c
  * @author  GEEKROS,  site:www.geekros.com
  ******************************************************************************
*/

#include "can.h"

Can_Struct Can_Data;

/******************************************************************
  * @ 函数名  ： Can_Init
  * @ 功能说明： CAN接口初始化，同时进行CAN1、CAN2接口的初始化
  * @ 参数    ： NULL 
  * @ 返回值  ： NULL
  *****************************************************************/
void Can_Init(void)
{
	Can1_Init();
	Can2_Init();
}

/******************************************************************
  * @ 函数名  ： Can1_Init
  * @ 功能说明： CAN1模块初始化，开发板共10组CAN1接口
  * @ 参数    ： NULL
  * @ 返回值  ： NULL
  *****************************************************************/
void Can1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

    GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1); 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    CAN_DeInit(CAN1);

    CAN_InitStructure.CAN_TTCM = DISABLE;
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = DISABLE;
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = DISABLE;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

    CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;
    CAN_InitStructure.CAN_Prescaler = 3;
    CAN_Init(CAN1, &CAN_InitStructure);

    CAN_FilterInitStructure.CAN_FilterNumber = 0;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);

    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
    CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
}

/******************************************************************
  * @ 函数名  ： Can2_Init
  * @ 功能说明： CAN2接口初始化，开发板共6组CAN2接口
  * @ 参数    ： NULL 
  * @ 返回值  ： NULL
  *****************************************************************/
void Can2_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_CAN2);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_CAN2); 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    CAN_DeInit(CAN2);

    CAN_InitStructure.CAN_TTCM = DISABLE;
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = DISABLE;
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = DISABLE;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

    CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;
    CAN_InitStructure.CAN_Prescaler = 3;
    CAN_Init(CAN2, &CAN_InitStructure);

    CAN_FilterInitStructure.CAN_FilterNumber = 0;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);

    CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);
    CAN_ITConfig(CAN2, CAN_IT_TME, ENABLE);
}

/******************************************************************
  * @ 函数名  ： CAN1_RX0_IRQHandler
  * @ 功能说明： CAN1中断回调函数
  * @ 参数    ： NULL
  * @ 返回值  ： NULL
  *****************************************************************/
void CAN1_RX0_IRQHandler(void)
{
	if(CAN_GetITStatus(CAN1,CAN_IT_FMP0) != RESET)
	{
		CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
		for(int i = 0;i < CAN_MOTOR_LEN;i++)
		{
			// 将CAN_Receive的数据存储到变量that_data
			CanRxMsg that_data;
			CAN_Receive(CAN1, CAN_FIFO0, &that_data);
			// 判断CAN_Receive数据中的电机ID值
			if(that_data.StdId == (0x140 + (i + 1)))
			{
				// 将数据传入统一回调函数进行处理
				CAN_Receive_Callback(that_data, 0, i);
			}
		}
	}
}

/******************************************************************
  * @ 函数名  ： CAN2_RX0_IRQHandler
  * @ 功能说明： CAN2中断回调函数
  * @ 参数    ： NULL
  * @ 返回值  ： NULL
  *****************************************************************/
void CAN2_RX0_IRQHandler(void)
{
	if (CAN_GetITStatus(CAN2,CAN_IT_FMP0) != RESET)
	{
		CAN_ClearITPendingBit(CAN2, CAN_IT_FMP0);
		for(int i = 0;i < CAN_MOTOR_LEN;i++)
		{
			// 将CAN_Receive的数据存储到变量that_data
			CanRxMsg that_data;
			CAN_Receive(CAN2, CAN_FIFO0, &that_data);
			// 判断CAN_Receive数据中的电机ID值
			if(that_data.StdId == (0x140 + (i + 1)))
			{
				// 将数据传入统一回调函数进行处理
				CAN_Receive_Callback(that_data, 1, i);
			}
		}
	}
}

/******************************************************************
  * @ 函数名  ： CAN_Receive_Callback
  * @ 功能说明： CAN中断数据统一回调函数
  * @ 参数    ： CanRxMsg* can_read_data 中断的回调数据
  * @ 参数    ： int channel CAN通道
  * @ 参数    ： int motor_id 电机ID
  * @ 返回值  ： NULL
  *****************************************************************/
void CAN_Receive_Callback(CanRxMsg can_read_data, int channel, int motor_id)
{
	// 根据不同的数据读取类型进行对应的存储操作
	if(can_read_data.Data[0] == 0x30)
	{
		// 读取到的PID数据
		Can_Data.Pid[channel][motor_id] = can_read_data;
		// 通过USB输出
		Usb_Write_Data("{\"type\":\"can-read-pid\",\"id\":%d,\"angle_kp\":%d,\"angle_ki\":%d,\"speed_kp\":%d,\"speed_ki\":%d,\"iq_kp\":%d,\"iq_ki\":%d}\r\n", \
		motor_id + 1, can_read_data.Data[2], can_read_data.Data[3], can_read_data.Data[4], can_read_data.Data[5], can_read_data.Data[6], can_read_data.Data[7]);
	}
}

/******************************************************************
  * @ 函数名  ： Can_Task
  * @ 功能说明： CAN任务函数，通过系统任务实时写入CAN通讯数据
  * @ 参数    ： NULL 
  * @ 返回值  ： NULL
  *****************************************************************/
void Can_Task(void)
{
	
}

/******************************************************************
  * @ 函数名  ： Can_Read_Pid
  * @ 功能说明： 发送PID数据读取协议
  * @ 参数    ： int channel 通道 可选值：1(CAN1)、2(CAN2)
  * @ 参数    ： int motor_id 电机ID 
  * @ 返回值  ： NULL
  *****************************************************************/
void Can_Read_Pid(int channel, int motor_id)
{
	if(motor_id > 0){
		if(channel == 1)
		{
			Can_Data.Can_Write_Data[0][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[0][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[0][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[0][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[0][motor_id-1].Data[0] = 0x30;
			CAN_Transmit(CAN1, &Can_Data.Can_Write_Data[0][motor_id-1]);
		}
		if(channel == 2)
		{
			Can_Data.Can_Write_Data[1][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[1][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[1][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[1][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[1][motor_id-1].Data[0] = 0x30;
			CAN_Transmit(CAN2, &Can_Data.Can_Write_Data[1][motor_id-1]);
		}
	}
}

/******************************************************************
  * @ 函数名  ： Can_Motor_Close
  * @ 功能说明： 发送电机关闭通讯协议
  * @ 参数    ： int channel 通道 可选值：1(CAN1)、2(CAN2)
  * @ 参数    ： int motor_id 电机ID 
  * @ 返回值  ： NULL
  *****************************************************************/
void Can_Motor_Close(int channel, int motor_id)
{
	if(motor_id > 0){
		if(channel == 1)
		{
			Can_Data.Can_Write_Data[0][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[0][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[0][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[0][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[0][motor_id-1].Data[0] = 0x80;
			CAN_Transmit(CAN1, &Can_Data.Can_Write_Data[0][motor_id-1]);
		}
		if(channel == 2)
		{
			Can_Data.Can_Write_Data[1][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[1][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[1][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[1][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[1][motor_id-1].Data[0] = 0x80;
			CAN_Transmit(CAN2, &Can_Data.Can_Write_Data[1][motor_id-1]);
		}
	}
}

/******************************************************************
  * @ 函数名  ： Can_Motor_Stop
  * @ 功能说明： 发送电机停止通讯协议
  * @ 参数    ： int channel 通道 可选值：1(CAN1)、2(CAN2)
  * @ 参数    ： int motor_id 电机ID 
  * @ 返回值  ： NULL
  *****************************************************************/
void Can_Motor_Stop(int channel, int motor_id)
{
	if(motor_id > 0){
		if(channel == 1)
		{
			Can_Data.Can_Write_Data[0][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[0][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[0][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[0][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[0][motor_id-1].Data[0] = 0x81;
			CAN_Transmit(CAN1, &Can_Data.Can_Write_Data[0][motor_id-1]);
		}
		if(channel == 2)
		{
			Can_Data.Can_Write_Data[1][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[1][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[1][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[1][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[1][motor_id-1].Data[0] = 0x81;
			CAN_Transmit(CAN2, &Can_Data.Can_Write_Data[1][motor_id-1]);
		}
	}
}

/******************************************************************
  * @ 函数名  ： Can_Motor_Run
  * @ 功能说明： 发送电机运行通讯协议
  * @ 参数    ： int channel 通道 可选值：1(CAN1)、2(CAN2)
  * @ 参数    ： int motor_id 电机ID 
  * @ 返回值  ： NULL
  *****************************************************************/
void Can_Motor_Run(int channel, int motor_id)
{
	if(motor_id > 0){
		if(channel == 1)
		{
			Can_Data.Can_Write_Data[0][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[0][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[0][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[0][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[0][motor_id-1].Data[0] = 0x88;
			CAN_Transmit(CAN1, &Can_Data.Can_Write_Data[0][motor_id-1]);
		}
		if(channel == 2)
		{
			Can_Data.Can_Write_Data[1][motor_id-1].RTR = CAN_RTR_DATA;
			Can_Data.Can_Write_Data[1][motor_id-1].IDE = CAN_ID_STD;
			Can_Data.Can_Write_Data[1][motor_id-1].DLC = 0x08;
			Can_Data.Can_Write_Data[1][motor_id-1].StdId = 0x140 + motor_id;
			Can_Data.Can_Write_Data[1][motor_id-1].Data[0] = 0x88;
			CAN_Transmit(CAN2, &Can_Data.Can_Write_Data[1][motor_id-1]);
		}
	}
}

/******************************************************************
  * @ 函数名  ： Led_Usb_Callback
  * @ 功能说明： 串口回调函数
  * @ 参数    ： char *type 类型 
  * @ 参数    ： int channel 通道 可选值：1(CAN1)、2(CAN2)
  * @ 参数    ： int motor_id 电机ID
  * @ 返回值  ： NULL
  *****************************************************************/
void Can_Usb_Callback(char *type, int channel, int motor_id)
{
	if(memcmp(type, "can-read-pid", 12) == 0)
	{
		Can_Read_Pid(channel, motor_id);
	}
}
